package com.topit.show.wxapi.common;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bike.util.TimeManager;
import com.topit.show.core.util.DigestUtils;
import com.topit.show.core.util.EmojiFilter;
import com.topit.show.core.util.StrUtil;
import com.topit.show.core.util.gson.GsonUtils;
import com.topit.show.wxapi.vo.AccessToken;
import com.topit.show.wxapi.vo.JsApiTicket;

public class WeixinApiUtil {
	private static final Logger log = LoggerFactory.getLogger(WeixinApiUtil.class);

	/**
	 * 发起https请求并获取结果
	 *
	 *
	 * @param appid
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return String(json对象)
	 */
	public static String httpRequest(String appid, String requestUrl, String requestMethod, String outputStr) throws Exception {
		StringBuilder buffer = new StringBuilder();
		String result = null;
		// 创建SSLContext对象，并使用我们指定的信任管理器初始化
		TrustManager[] tm = { new MyX509TrustManager() };
		SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
		sslContext.init(null, tm, new java.security.SecureRandom());
		// 从上述SSLContext对象中得到SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();

		URL url = new URL(requestUrl);
		HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
		httpUrlConn.setSSLSocketFactory(ssf);

		httpUrlConn.setDoOutput(true);
		httpUrlConn.setDoInput(true);
		httpUrlConn.setUseCaches(false);

		// 设置请求方式（GET/POST）
		httpUrlConn.setRequestMethod(requestMethod);

		if ("GET".equalsIgnoreCase(requestMethod))
			httpUrlConn.connect();

		// 当有数据需要提交时
		if (null != outputStr) {
			OutputStream outputStream = httpUrlConn.getOutputStream();
			// 注意编码格式，防止中文乱码
			outputStream.write(outputStr.getBytes("UTF-8"));
			outputStream.close();
		}

		// 将返回的输入流转换成字符串
		InputStream inputStream = httpUrlConn.getInputStream();
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

		String str;
		while ((str = bufferedReader.readLine()) != null) {
			buffer.append(str);
		}
		result = buffer.toString();
		if (log.isDebugEnabled()) {
			log.debug("请求微信接口：{}， 返回：{}", requestUrl, result);
		}
		bufferedReader.close();
		inputStreamReader.close();
		// 释放资源
		inputStream.close();
		inputStream = null;
		httpUrlConn.disconnect();
		return EmojiFilter.filterEmoji(result);
	}

	/**
	 * 获取access_token
	 *
	 * @param appid
	 *            凭证
	 * @param appsecret
	 *            密钥
	 * @return accessToken
	 */
	public static AccessToken getAccessToken(String appid, String appsecret) {
		AccessToken accessToken = AccessTokenContainer.get(appid);
		
		if (accessToken == null || accessToken.isExpires() ) {
			String requestUrl = WeixinApiUrl.access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
			String response;
			try {
				response = httpRequest(appid, requestUrl, "GET", null);
				accessToken = GsonUtils.fromJson(response, AccessToken.class);
				// 如果请求成功
				if (null != accessToken) {
					accessToken.setGetTime(System.currentTimeMillis());
					AccessTokenContainer.put(appid, accessToken);
				} else {
					ErrorCode errorCode = GsonUtils.fromJson(response, ErrorCode.class);
					log.error("获取accessToken异常，appid={}，错误原因={}", appid, errorCode.toString());
				}
			} catch (Exception e) {
				log.error("获取accessToken异常，appid={}，错误原因={}", appid, e.getMessage());
			}
		}

		return accessToken;
	}

	/**
	 * 获取jsapi_ticket
	 *
	 * @param appid
	 *            凭证
	 * @param appsecret
	 *            密钥
	 * @return accessToken
	 */
	public static String getJsApiTicket(String appid, String appsecret) {
		JsApiTicket jsApiTicket = JsApiTicketContainer.get(appid);
		AccessToken accessToken = getAccessToken(appid, appsecret);
		if (accessToken == null) {
			return null;
		}

		if (jsApiTicket == null) {
			String requestUrl = WeixinApiUrl.jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken.getAccess_token());
			String response;
			try {
				response = httpRequest(appid, requestUrl, "GET", null);
				jsApiTicket = GsonUtils.fromJson(response, JsApiTicket.class);
				// 如果请求成功
				if (null != jsApiTicket) {
					jsApiTicket.setGetTime(System.currentTimeMillis());
					JsApiTicketContainer.put(appid, jsApiTicket);
				} else {
					ErrorCode errorCode = GsonUtils.fromJson(response, ErrorCode.class);
					log.error("获取jsapi_ticket异常，appid={}，错误原因={}", appid, errorCode.toString());
				}
			} catch (Exception e) {
				log.error("获取jsapi_ticket异常，appid={}，错误原因={}", appid, e.getMessage());
			}
		}

		if (jsApiTicket != null) {
			return jsApiTicket.getTicket();
		} else {
			return null;
		}

	}

	/**
	 * 判断是否是QQ表情
	 *
	 * @param content
	 * @return
	 */
	public static boolean isQqFace(String content) {
		boolean result = false;

		// 判断QQ表情的正则表达式
		String qqfaceRegex = "/::\\)|/::~|/::B|/::\\||/:8-\\)|/::<|/::$|/::X|/::Z|/::'\\(|/::-\\||/::@|/::P|/::D|/::O|/::\\(|/::\\+|/:--b|/::Q|/::T|/:,@P|/:,@-D|/::d|/:,@o|/::g|/:\\|-\\)|/::!|/::L|/::>|/::,@|/:,@f|/::-S|/:\\?|/:,@x|/:,@@|/::8|/:,@!|/:!!!|/:xx|/:bye|/:wipe|/:dig|/:handclap|/:&-\\(|/:B-\\)|/:<@|/:@>|/::-O|/:>-\\||/:P-\\(|/::'\\||/:X-\\)|/::\\*|/:@x|/:8\\*|/:pd|/:<W>|/:beer|/:basketb|/:oo|/:coffee|/:eat|/:pig|/:rose|/:fade|/:showlove|/:heart|/:break|/:cake|/:li|/:bome|/:kn|/:footb|/:ladybug|/:shit|/:moon|/:sun|/:gift|/:hug|/:strong|/:weak|/:share|/:v|/:@\\)|/:jj|/:@@|/:bad|/:lvu|/:no|/:ok|/:love|/:<L>|/:jump|/:shake|/:<O>|/:circle|/:kotow|/:turn|/:skip|/:oY|/:#-0|/:hiphot|/:kiss|/:<&|/:&>";
		Pattern p = Pattern.compile(qqfaceRegex);
		Matcher m = p.matcher(content);
		if (m.matches()) {
			result = true;
		}
		return result;
	}

	/**
	 * 获取微信jsAPI 认证时需要的参数
	 * 
	 * @param appId
	 * @param appSecret
	 * @return
	 */
	public static HashMap<String, String> getJsApiConfigMap(String appId, String appSecret, String url) {

		// 如果该页面已经认证就不需要认证了
		// if (url2JsConfigMap.get(url) != null) {
		// return null;
		// }

		// 设置认证参数
		String jsapi_ticket = WeixinApiUtil.getJsApiTicket(appId, appSecret);
		if (jsapi_ticket == null) {
			if (log.isDebugEnabled()) {
				log.debug("getJsApiConfigMap : 获取jsapi_ticket失败");
			}
			return null;
		}

		String timestamp = "" + System.currentTimeMillis();
		String nonceStr = StrUtil.getRandomString(16);
		String str = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
		String signature = "";
		try {
			signature = DigestUtils.sha(str);
		} catch (NoSuchAlgorithmException e) {
			log.error("getJsApiConfigMap", e);
			return null;
		}

		HashMap<String, String> wxConfigMap = new HashMap<String, String>();
		wxConfigMap.put("timestamp", timestamp);
		wxConfigMap.put("appId", appId);
		wxConfigMap.put("nonceStr", nonceStr);
		wxConfigMap.put("signature", signature);
		wxConfigMap.put("url", url);

		return wxConfigMap;
	}

	public static void main(String[] args) {
		// AccessToken token = getAccessToken("wx386f16b7e29a71e5",
		// "7bf76d1b8e5f9de510375cca7e0e471a");
		// if (token != null) {
		// System.out.println(token.toString());
		// }
	}
}
